package loan.calc.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import loan.calc.util.SnowFlake;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

@Configuration
@MapperScan("loan.calc.mapper")
@Slf4j
public class MybatisAutoConfiguration {

    /**
     * mybatis-plus配置
     * @return
     */
    @Bean
    public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer(SnowFlake snowFlake) {
        return plusProperties -> {
            // 隐藏banner
            plusProperties.getGlobalConfig().setBanner(false);
            // 全局主键生成器->雪花算法
            plusProperties.getGlobalConfig().setIdentifierGenerator(entity -> snowFlake.nextId());
            // 全局逻辑删除字段名
            plusProperties.getGlobalConfig().getDbConfig().setLogicDeleteField("deleted");
            // mapper.xml自动扫描路径
            plusProperties.setMapperLocations(new String[]{"classpath*:/mapper/**/*Mapper.xml"});
            // mybatis.configuration
            if (plusProperties.getConfiguration() == null) {
                plusProperties.setConfiguration(new MybatisConfiguration());
            }
            // 日志实现
            plusProperties.getConfiguration().setLogImpl(Slf4jImpl.class);
            // 枚举处理器
            plusProperties.getConfiguration().setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);
        };
    }

    /**
     * 插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 防全表更新与删除插件
        // interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        // 乐观锁
        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);
        // 分页插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(false);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MetaObjectHandler() {
            @Override
            public void insertFill(MetaObject metaObject) {
                this.strictInsertFill(metaObject, "version", Integer.class, 0); // 起始版本 3.3.0(推荐使用)
                this.strictInsertFill(metaObject, "createdTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
                this.strictInsertFill(metaObject, "createdBy", Long.class, 0L); // 起始版本 3.3.0(推荐使用)
                this.strictUpdateFill(metaObject, "updatedTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
                this.strictUpdateFill(metaObject, "updatedBy", Long.class, 0L); // 起始版本 3.3.0(推荐)
                // 或者
                // this.strictInsertFill(metaObject, "createdTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
            }

            @Override
            public void updateFill(MetaObject metaObject) {
                this.strictUpdateFill(metaObject, "updatedTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
                this.strictUpdateFill(metaObject, "updatedBy", Long.class, 0L); // 起始版本 3.3.0(推荐)
                // 或者
                // this.strictUpdateFill(metaObject, "updatedTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
            }
        };
    }
}
